#include <iostream>
#include <vector>
#include <string>
#include <unistd.h>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

using std::exception;

// 服务器开发中通常使用的异常继承体系
class Exception
{
public:
    Exception(const string &errmsg, int id)
        : _errmsg(errmsg), _id(id)
    {
    }

    virtual string what() const
    {
        return _errmsg;
    }

protected:
    string _errmsg; // 错误描述
    int _id;        // 错误id
};

class SqlException : public Exception
{
public:
    SqlException(const string &errmsg, int id, const string &sql)
        : Exception(errmsg, id), _sql(sql)
    {
    }
    virtual string what() const // 库里面what函数作用是：发生了什么，也就是获取错误函数信息
    {
        string str = "SqlException:";
        str += _errmsg;
        str += "->";
        str += _sql;
        return str;
    }

private:
    const string _sql;
};

class CacheException : public Exception
{
public:
    CacheException(const string &errmsg, int id)
        : Exception(errmsg, id)
    {
    }
    virtual string what() const
    {
        string str = "CacheException:";
        str += _errmsg;
        return str;
    }
};

class HttpServerException : public Exception
{
public:
    HttpServerException(const string &errmsg, int id, const string &type)
        : Exception(errmsg, id) // 父类调用父类的构造函数
          ,
          _type(type)
    {
    }
    virtual string what() const
    {
        string str = "HttpServerException:";
        str += _type;
        str += ":";
        str += _errmsg;
        return str;
    }

private:
    const string _type;
};

void SQLMgr()
{
    srand(time(0));
    if (rand() % 7 == 0)
    {
        throw SqlException("权限不足", 100, "select * from name = '张三'");
    }
    cout << "调用成功" << endl;
}

void CacheMgr()
{
    srand(time(0));
    if (rand() % 5 == 0)
    {
        throw CacheException("权限不足", 100);
        // throw 1;
    }
    else if (rand() % 6 == 0)
    {
        throw CacheException("数据不存在", 101);
    }
    SQLMgr();
}

void HttpServer()
{
    // ...
    srand(time(0));
    if (rand() % 3 == 0)
    {
        throw HttpServerException("请求资源不存在", 100, "get");
    }
    else if (rand() % 4 == 0)
    {
        throw HttpServerException("权限不足", 101, "post");
    }
    CacheMgr();
}

int main()
{
    while (1)
    {
        // Sleep(1000);
        sleep(1);
        try
        {
            HttpServer();
        }
        catch (const Exception &e) // 这里捕获父类对象就可以
        {
            // 多态
            cout << e.what() << endl;
        }
        catch (const exception &e)
        {
            // ...
            cout << e.what() << endl;
        }
        catch (...) // 捕获未知异常
        {
            cout << "Unkown Exception" << endl;
        }
    }
    return 0;
}

// int main()
// {
// 	try {
// 		vector<int> v(10, 5);
// 		// 这里如果系统内存不够也会抛异常
// 		v.reserve(10000000000000000);

// 		// 这里越界会抛异常
// 		v.at(10) = 100;
// 	}
// 	catch (const exception& e) // 这里捕获父类对象就可以
// 	{
// 		cout << e.what() << endl;
// 	}
// 	catch (...)
// 	{
// 		cout << "Unkown Exception" << endl;
// 	}
// 	return 0;
// }

// double Division(int a, int b) throw(string)
// {
//     if (b == 0)
//     {
//         string s("Division by zero condition!");
//         throw s; // 这里s抛出之后，出了作用域就销毁了，那么下面的catch捕获的是什么呢
//         // 编译器把s识别为右值，将亡值，直接移动拷贝构造
//     }
//     else
//         return ((double)a / (double)b);
// }
// double Division2(int a, int b) throw(string)
// {

//     if (b != 0)
//     {
//         string s("zero zero zero!!!");
//         throw s; // 这里s抛出之后，出了作用域就销毁了，那么下面的catch捕获的是什么呢
//         // 编译器把s识别为右值，将亡值，直接移动拷贝构造
//     }
// }
// void Func()
// {

//     int len, time;
//     cin >> len >> time;
//     cout << Division(len, time) << endl;
//     cout << Division2(len, time) << endl;
// }
// int main()
// {
//     try
//     {
//         Func();
//     }
//     catch (const string error)
//     {
//         cout << error << endl;
//     }
//     catch (...) // 捕获任意类型的异常，发现异常直接终止程序是不对的，异常没有捕获可以报错，但是不能够终止进程
//     {
//         cout << "未知异常" << endl;
//     }
//     return 0;
// }

// double Division(int a, int b)
// {
// 	if (b == 0)
// 		throw "Division by zero condition!";
// 	else
// 		return ((double)a / (double)b);
// }
// void Func()
// {
// 	int* p1 = new int[10];
// 	try
// 	{
// 		int len, time;
// 		cin >> len >> time;
// 		cout << Division(len, time) << endl; // 这里throw的是const char*对象
// 		// func()   // throw double对象 —— 如果这里还有函数要抛其他类型的对象，我们不是要n个catch才能捕获吗？
// 	}

// 	catch (...)  // 这里用...就行了，表示可以捕获任意类型的异常
// 	{
// 		cout << "delete" << p1 << endl;
// 		delete[] p1;

// 		throw;
// 	}
// 	cout << "delete"<< p1 << endl;
// 	delete[] p1;
// }

// int main()
// {
// 	try
// 	{
// 		Func();
// 	}
// 	catch (const char* errmsg)
// 	{
// 		cout << errmsg << endl;
// 	}
// 	catch (int errid)
// 	{
// 		cout << errid << endl;
// 	}
// 	return 0;
// }

// double Division(int a, int b)
// {
// 	// 当b == 0时抛出异常
// 	if (b == 0)//除0错误
// 		throw "Division by zero condition!";//throw + 对象 —— 对象可以是任意类型对象
// 	else
// 		return ((double)a / (double)b);
// }
// //void Func()
// //{
// //	int len, time;
// //	cin >> len >> time;
// //	cout << Division(len, time) << endl;
// //}
// void Func()
// {
// 	int* p1 = new int[10];
// 	try//但是这里代码太过于冗杂了，等我们下一节的智能指针学了就可以不需要这么多的代码了
// 	{
// 		int len, time;
// 		cin >> len >> time;
// 		cout << Division(len, time) << endl;
// 	}
// 	catch (const char* errmsg)
// 	{
// 		cout << "delete" << p1 << endl;
// 		delete[] p1;//先释放，然后再抛出
// 		throw errmsg;  // 重新抛出
// 	}
// 	cout << "delete"<< p1 << endl;
// 	delete[] p1;
// }
// int main()
// {
// 	try//我们自己调试的时候，不会走try这行代码，直接走下面的Func（）函数
// 	{
// 		Func();
// 	}
// 	catch (const char* errmsg) //没有抛异常直接跳过catch。有了抛异常直接跳到catch函数
// 		//这里没有const就无法捕获，会直接报错终止
// 	{
// 		cout << errmsg << endl;
// 		// 记录日志，进行统一处理
// 	}
// 	catch (int errid)
// 	{
// 		cout << errid << endl;
// 	}
// 	return 0;
// }

// double Division(int a, int b)
// {
//     // 当b == 0时抛出异常
//     if (b == 0)
//     {
//         throw "Division by zero condition!";
//     }
//     return (double)a / (double)b;
// }

// void Func()
// {
//     // 这里可以看到如果发生除0错误抛出异常，另外下面的array没有得到释放。

//     // 所以这里捕获异常后并不处理异常，异常还是交给外面处理，这里捕获了再

//     // 重新抛出去。

//     int *array = new int[10];
//     try
//     {
//         int len, time;
//         cin >> len >> time;
//         cout << Division(len, time) << endl;
//     }
//     catch (...)
//     {
//         cout << "delete []" << array << endl;
//         delete[] array;
//         throw;
//     }
//     // ...

//     cout << "delete []" << array << endl;
//     delete[] array;
// }
// int main()
// {
//     try
//     {
//         Func();
//     }
//     catch (const char *errmsg)
//     {
//         cout << errmsg << endl;
//     }
//     return 0;
// }

// double Division(int a, int b)
// {
// 	// 当b == 0时抛出异常
// 	if (b == 0)//除0错误
// 		throw 1;//throw + 对象 —— 对象可以是任意类型对象
// 	else
// 		return ((double)a / (double)b);
// }
// void Func()
// {
// 	int len, time;
// 	cin >> len >> time;
// 	cout << Division(len, time) << endl;
// }
// int main()
// {
// 	try//我们自己调试的时候，不会走try这行代码，直接走下面的Func（）函数
// 	{
// 		Func();
// 	}
// 	catch (const char* errmsg) //没有抛异常直接跳过catch。有了抛异常直接跳到catch函数
// 	{
// 		cout << "异常" <<errmsg << endl;
// 		// 记录日志，进行统一处理
// 	}
// 	catch (int errid)
// 	{
// 		cout << "异常错误码" << errid << endl;
// 	}
// 	return 0;
// }

// double Division(int a, int b)
// {
// 	// 当b == 0时抛出异常
// 	if (b == 0)//除0错误
// 		throw "Division by zero condition!";//throw + 对象 —— 对象可以是任意类型对象
// 	else
// 		return ((double)a / (double)b);
// }
// void Func()
// {
// 	int len, time;
// 	cin >> len >> time;
// 	cout << Division(len, time) << endl;
// }
// int main()
// {
// 	try//我们自己调试的时候，不会走try这行代码，直接走下面的Func（）函数
// 	{
// 		Func();
// 	}
// 	catch (const char* errmsg) //没有抛异常直接跳过catch。有了抛异常直接跳到catch函数
// 	{
// 		cout << "异常" <<errmsg << endl;
// 		// 记录日志，进行统一处理
// 	}
// 	catch (int errid)
// 	{
// 		cout << errid << endl;
// 	}
// 	return 0;
// }
